package com.tang.lts.core.autoconfigure;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.*;

/**
 * @author Tang
 * @classname AutoConfigContextBuilder
 * @description [  ]
 * @date 2022/4/12 21:50
 */
public class AutoConfigContextBuilder {

    private Object targetObject;

    private String prefix;

    private HashMap<String, String> propsMap;

    /**
     * 属性的自省
     */
    private Map<String, PropertyDescriptor> namePropertyDescriptorMap;

    private List<PropertyDescriptor> propertyDescriptors;

    private Map<String, PropertyDescriptor> namePropertyDescriptorsMap;

    public AutoConfigContextBuilder setTargetObject(Object targetObject) {
        this.targetObject = targetObject;
        return this;
    }

    public AutoConfigContextBuilder setPrefix(String prefix) {
        this.prefix = prefix;
        return this;
    }

    public AutoConfigContextBuilder setPropsMap(HashMap<String, String> propsMap) {
        this.propsMap = propsMap;
        return this;
    }

    public AutoConfigContext build() {

        buildPropertyDescriptors();

        buildNamePropertyDescriptorsMap(prefix,propertyDescriptors);

        return new AutoConfigContext(namePropertyDescriptorMap,propsMap,targetObject);
    }

    private void buildNamePropertyDescriptorsMap(String prefix, List<PropertyDescriptor> propertyDescriptors) {
        namePropertyDescriptorMap = new HashMap<>();
        Iterable<String> prefixes = RelaxedNames.forCameCase(prefix);
        for (PropertyDescriptor pd : propertyDescriptors) {
            RelaxedNames relaxedNames = RelaxedNames.forCameCase(pd.getName());
            for (String _prefix : prefixes) {
                for (String relaxedName : relaxedNames) {
                    String name1 = _prefix + "." + relaxedName;
                    String name2 = _prefix + "_" + relaxedName;
                    namePropertyDescriptorMap.put(name1, pd);
                    namePropertyDescriptorMap.put(name2, pd);
                }
            }
        }
    }

    private void buildPropertyDescriptors() {
        propertyDescriptors = new ArrayList<>();
        Class<?> aClass = targetObject.getClass();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(aClass, Object.class, Introspector.IGNORE_ALL_BEANINFO);
            propertyDescriptors.addAll(Arrays.asList(beanInfo.getPropertyDescriptors()));
        } catch (IntrospectionException e) {
            e.printStackTrace();
        }
    }
}